﻿/*  
 * Helix Engine
 * http://helixengine.codeplex.com/
 * 
 * Copyright (c) 2010 - 2011 Joe Hegarty
 *  
 * This source code is subject to the terms of the Microsoft Public License (Ms-PL). 
 *  
 * Redistribution and use in source and binary forms, with or without modification, 
 * is permitted provided that redistributions of the source code retain the above 
 * copyright notices and this file header. 
 * 
 * For details please see http://www.opensource.org/licenses/ms-pl.html 
 *  
 * All other rights reserved. 
 *
 */  


using System;
namespace HelixEngine.Maths
{
    /// <remarks>
    /// 
    /// </remarks>
    public class MathHelper
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="degrees"></param>
        /// <returns></returns>
        public static double DegreesToRadians(double degrees)
        {
            double radians = ((degrees / 360) * 2 * Math.PI);
            return radians;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="angleInDegrees"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static Vector2 CreateVector2FromAngle(double angleInDegrees, double length)
        {
            double x = Math.Sin(DegreesToRadians(180 - angleInDegrees)) * length;
            double y = Math.Cos(DegreesToRadians(180 - angleInDegrees)) * length;
            return new Vector2(x, y);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public static double Lerp(double value1, double value2, double amount)
        {
            return value1 + (value2 - value1) * amount;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="tangent1"></param>
        /// <param name="value2"></param>
        /// <param name="tangent2"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public static double Hermite(double value1, double tangent1, double value2, double tangent2, double amount)
        {
            double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
            double sCubed = s * s * s;
            double sSquared = s * s;

            if (amount == 0f)
            {
                result = value1;
            }
            else if (amount == 1f)
            {
                result = value2;
            }
            else
            {
                result = (2 * v1 - 2 * v2 + t2 + t1) * sCubed +
                    (3 * v2 - 3 * v1 - 2 * t1 - t2) * sSquared +
                    t1 * s +
                    v1;
            }

            return (float)result;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static double Clamp(double value, double min, double max)
        {
            value = (value > max) ? max : value;
            value = (value < min) ? min : value;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public static double SmoothStep(double value1, double value2, double amount)
        {
            double result = MathHelper.Clamp(amount, 0f, 1f);
            result = MathHelper.Hermite(value1, 0f, value2, 0f, result);
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        /// <returns></returns>
        public static double Max(double value1, double value2)
        {
            return Math.Max(value1, value2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        /// <returns></returns>
        internal static double Min(double value1, double value2)
        {
            return Math.Max(value1, value2);
        }
    }
}
